package com.yi.controller;

import cn.hutool.json.JSONUtil;
import com.yi.model.Baike;
import com.yi.model.User;
import com.yi.service.MongoDbBaiKeService;
import com.yi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.List;

/**
 * Redis操作
 * @author YI
 * @date 2018-3-20 16:15:53
 */
@Controller
@RequestMapping("/redis")
public class RedisCrontroller {
    @Autowired
    UserService userService;
    @Autowired
    MongoDbBaiKeService mongoDbBaiKeService;
    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     * 用于地理信息 添加一个ZSET的结构 CHINA:CITY
     */
    public static String key = "CHINA:CITY";

    /**
     * 往redis中写入数据
     * @return
     */
    @RequestMapping("/simpleSet")
    @ResponseBody
    public String simpleSet(){
        List<User> list = userService.findUser(1);
        Baike baike = mongoDbBaiKeService.findById("1");

        redisTemplate.opsForValue().set("user", JSONUtil.toJsonPrettyStr(list));
        redisTemplate.opsForValue().set("baike", JSONUtil.toJsonPrettyStr(baike));

        return "Success";
    }

    /**
     * 读取redis中的数据
     * @return
     */
    @RequestMapping("/simpleGet")
    @ResponseBody
    public List simpleGet(){
        List<Object> list = new ArrayList<>();
        String user = redisTemplate.opsForValue().get("user");
        String baike = redisTemplate.opsForValue().get("baike");

        list.add(JSONUtil.parseArray(user).toList(User.class));
        list.add(JSONUtil.toBean(JSONUtil.parseObj(baike), Baike.class));

        return list;
    }

    /**
     * 发送消息 支持基于Redis的消息订阅/发布消息
     * @return
     */
    @RequestMapping("/pub")
    @ResponseBody
    public String pub(String message) {
        redisTemplate.convertAndSend("news.message", message);

        return "Success";
    }

    /**
     *  地理信息查询
     */
    @RequestMapping("/geo")
    @ResponseBody
    public List geo() {
        List<Object> geoList = new ArrayList<>();

        //用于地理信息 添加一个ZSET的结构 CHINA:CITY
        BoundGeoOperations boundGeoOperations = redisTemplate.boundGeoOps(key);
        //南京市 118.803805,32.060168
        Point nanjing = new Point(118.803805,32.060168);
        //北京市 116.397039,39.9077
        Point beijing = new Point(116.397039,39.9077);
        //天津市 116.397039,39.9077
        Point tianjing = new Point(117.20,39.12);

        //添加地理信息到Redis
        System.out.println(boundGeoOperations.add(nanjing, "南京市"));
        System.out.println(boundGeoOperations.add(beijing, "北京市"));
        System.out.println(boundGeoOperations.add(tianjing, "天津市"));

        //获取某个地理位置的geohash值
        List<String> list = boundGeoOperations.hash("南京市");
        System.out.println("南京市的geoHash = " + list.get(0));
        geoList.add("南京市的geoHash = " + list.get(0));

        //获取某个地理位置的坐标
        List<Point> pointList = boundGeoOperations.position("南京市");
        System.out.println("南京市的经纬度为 = " + pointList.get(0));
        geoList.add("南京市的经纬度为 = " + pointList.get(0));

        //获取两个地理位置的距离
        Distance distance = boundGeoOperations.distance("南京市", "天津市", Metrics.KILOMETERS);
        System.out.println("南京市到天津市之间的距离是：" + distance.getValue() + "km");
        geoList.add("南京市到天津市之间的距离是：" + distance.getValue() + "km");

        //根据给定地理位置坐标获取指定范围内的地理位置集合
        //查询南京市1000KM范围内的城市
        Circle within = new Circle(nanjing,1000000);
        //设置geo查询参数
        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        //查询返回结果包括距离和坐标
        geoRadiusArgs = geoRadiusArgs.includeCoordinates().includeDistance();
        //按查询出的坐标距离中心坐标的距离进行排序
        geoRadiusArgs.sortAscending();
        //限制查询返回的数量
        geoRadiusArgs.limit(5);
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = boundGeoOperations.radius(within,geoRadiusArgs);
        List<GeoResult<RedisGeoCommands.GeoLocation<String>>> geoResultList = geoResults.getContent();
        for (GeoResult geoResult : geoResultList) {
            System.out.println("geoRadius  " + geoResult.getContent());
            geoList.add("geoRadius  " + geoResult.getContent());
        }

        //根据给定地理位置获取指定范围内的地理位置集合 查询南京市800KM范围内的城市
        geoResults = boundGeoOperations.radius("南京市",new Distance(800000), geoRadiusArgs);
        geoResultList = geoResults.getContent();
        for (GeoResult geoResult : geoResultList) {
            System.out.println("radius  " + geoResult.getContent());
            geoList.add("radius  " + geoResult.getContent());
        }

        //删除位置信息,此命令不是geo提供的，是使用zrem命令删除的
//        System.out.println(boundGeoOperations.remove("南京市"));

        return geoList;
    }
}
